package com.example.rxohosaudio;

import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;
import ohos.media.audio.*;

@SuppressWarnings({"unused", "WeakerAccess", "UnusedReturnValue"})
public final class StreamAudioPlayer {
    private static final String TAG = "StreamAudioPlayer";
    private HiLogLabel label = new HiLogLabel(HiLog.LOG_APP, 0x00201, "StreamAudioPlayer");

    public static final int DEFAULT_SAMPLE_RATE = 44100;
    private AudioRenderer mAudioRenderer;
    private AudioStreamInfo audioStreamInfo;

    private StreamAudioPlayer() {
        // singleton
    }

    private static final class StreamAudioPlayerHolder {
        private static final StreamAudioPlayer INSTANCE = new StreamAudioPlayer();
    }

    public static StreamAudioPlayer getInstance() {
        return StreamAudioPlayerHolder.INSTANCE;
    }

    public synchronized void init() {
        init(DEFAULT_SAMPLE_RATE, (AudioStreamInfo.ChannelMask.CHANNEL_OUT_MONO), (AudioStreamInfo.EncodingFormat.ENCODING_PCM_16BIT),
                StreamAudioRecorder.DEFAULT_BUFFER_SIZE);
    }

    /**
     * AudioFormat.CHANNEL_OUT_MONO
     * AudioFormat.ENCODING_PCM_16BIT
     *
     * @param bufferSize user may want to write data larger than minBufferSize, so they should able
     * to increase it
     */
    public synchronized void init(final int sampleRate, final AudioStreamInfo.ChannelMask channelConfig, final AudioStreamInfo.EncodingFormat audioFormat,
                                  final int bufferSize) {
        if (mAudioRenderer != null) {
            mAudioRenderer.release();
            mAudioRenderer = null;
        }
        int minBufferSize = AudioRenderer.getMinBufferSize(sampleRate, audioFormat, channelConfig);

        audioStreamInfo = new AudioStreamInfo.Builder().sampleRate(DEFAULT_SAMPLE_RATE) // 44.1kHz
                .audioStreamFlag(AudioStreamInfo.AudioStreamFlag.AUDIO_STREAM_FLAG_MAY_DUCK) // 混音
                .encodingFormat(AudioStreamInfo.EncodingFormat.ENCODING_PCM_16BIT) // 16-bit PCM
                .channelMask(AudioStreamInfo.ChannelMask.CHANNEL_OUT_STEREO) // 双声道输出
                .streamUsage(AudioStreamInfo.StreamUsage.STREAM_USAGE_MEDIA) // 媒体类音频
                .build();

        AudioRendererInfo audioRendererInfo = new AudioRendererInfo.Builder().audioStreamInfo(audioStreamInfo)
                .audioStreamOutputFlag(AudioRendererInfo.AudioStreamOutputFlag.AUDIO_STREAM_OUTPUT_FLAG_DIRECT)
                .bufferSizeInBytes(100)
                .isOffload(false)
                .sessionID(AudioRendererInfo.SESSION_ID_UNSPECIFIED)
                .build();

        mAudioRenderer = new AudioRenderer(audioRendererInfo, (AudioRenderer.PlayMode.MODE_STREAM));
        mAudioRenderer.start();
    }

    //TODO:@WorkerThread
    public synchronized boolean play(final byte[] data, final int size) {
        if (mAudioRenderer != null) {
            try {
                boolean ret = (mAudioRenderer.write(data, 0, size));
                if (ret) {
                    return true;
                } else {
                    return false;
                }
            } catch (IllegalStateException e) {
                HiLog.warn(label, "play fail: " + e.getMessage());
                return false;
            }
        }
        HiLog.warn(label, "play fail: null mAudioTrack");
        return false;
    }

    public synchronized void release() {
        if (mAudioRenderer != null) {
            mAudioRenderer.release();
            mAudioRenderer = null;
        }
    }
}
